﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using Urb.Weather.Core;
using System.Xml.XPath;
using Urb.Weather.Core.Util;

namespace Urb.Weather.MSN
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "MSN")]
    public class MSNResponseAnalyzer
    {
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public MSNWeatherData Analyze(string response)
        {
            XPathNavigator navigator = XmlResponseAnalyzerHelper.ValidateResponseParametersAndCreateNavigator(response);

            MSNWeatherData result = new MSNWeatherData();

            navigator.ReadSingleNode(
                "/weatherdata/weather/@weatherlocationcode", (v) => result.WeatherLocationCode = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/@weatherlocationname", (v) => result.WeatherLocationName = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/@zipcode", (v) => result.ZipCode = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/@encodedlocationname", (v) => result.EncodedLocationName = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/@degreetype", (v) => result.DegreeType = v.ConvertToTemperatureUnit());
            navigator.ReadSingleNode(
                "/weatherdata/weather/@lat", (v) => result.Latitude = v.ConvertToDecimal());
            navigator.ReadSingleNode(
                "/weatherdata/weather/@long", (v) => result.Longitude = v.ConvertToDecimal());
            navigator.ReadSingleNode(
                "/weatherdata/weather/@timezone", (v) => result.TimeZone = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/@alert", (v) => result.Alert = v);
            
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@temperature", (v) => result.Temperature = v.ConvertToShort());
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@skycode", (v) => result.SkyCode = v.ConvertToShort());
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@skytext", (v) => result.SkyText = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@date", (v) => result.Date = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@day", (v) => result.Day = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@shortday", (v) => result.ShortDay = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@observationtime", (v) => result.ObservationTime = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@observationpoint", (v) => result.ObservationPoint = v);
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@feelslike", (v) => result.FeelsLike = v.ConvertToShort());
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@humidity", (v) => result.Humidity = v.ConvertToShort());
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@windspeed", (v) => result.WindSpeed = v.ConvertToShort());
            navigator.ReadSingleNode(
                "/weatherdata/weather/current/@winddisplay", (v) => result.WindDisplay = v);
            
            AnalyzeForecast(navigator, result);

            result.SourceXml = response;

            return result;
        }

        private static void AnalyzeForecast(XPathNavigator navigator, MSNWeatherData result)
        {
            XPathNodeIterator iterator = navigator.Select("/weatherdata/weather/forecast");

            List<MSNWeatherForecastData> forecastDatas = new List<MSNWeatherForecastData>();

            if (iterator != null)
            {
                foreach (XPathNavigator nodeNavigator in iterator)
                {
                    MSNWeatherForecastData forecastData = new MSNWeatherForecastData();

                    nodeNavigator.ReadSingleNode(
                        "@low", (v) => forecastData.Low = v.ConvertToShort());
                    nodeNavigator.ReadSingleNode(
                        "@high", (v) => forecastData.High = v.ConvertToShort());
                    nodeNavigator.ReadSingleNode(
                        "@skycodeday", (v) => forecastData.SkyCodeDay = v.ConvertToShort());
                    nodeNavigator.ReadSingleNode(
                        "@skytextday", (v) => forecastData.SkyTextDay = v);
                    nodeNavigator.ReadSingleNode(
                        "@date", (v) => forecastData.Date = v);
                    nodeNavigator.ReadSingleNode(
                        "@day", (v) => forecastData.Day = v);
                    nodeNavigator.ReadSingleNode(
                        "@shortday", (v) => forecastData.ShortDay = v);
                    nodeNavigator.ReadSingleNode(
                        "@precip", (v) => forecastData.Precipitation = v.ConvertToShort());

                    forecastDatas.Add(forecastData);
                }
            }

            result.Forecasts = forecastDatas.AsReadOnly();
        }
    }
}
